import type { AccessoryConfig, PlatformConfig } from '../bridgeService.js'

import { Logger } from '../logger.js'
import { checkPortProximity, validatePort } from './matterValidation.js'

const log = Logger.withPrefix('Matter')

export interface MatterConfigValidationResult {
  isValid: boolean
  errors: string[]
  warnings: string[]
}

/**
 * Validate Matter configuration for production readiness
 */
export class MatterConfigValidator {
  /**
   * Validate a Matter configuration object
   */
  static validate(config: Record<string, unknown>): MatterConfigValidationResult {
    const result: MatterConfigValidationResult = {
      isValid: true,
      errors: [],
      warnings: [],
    }

    // Validate port configuration
    this.validatePort(config, result)

    result.isValid = result.errors.length === 0

    if (result.warnings.length > 0) {
      log.warn('Matter configuration warnings:')
      result.warnings.forEach(warning => log.warn(`  - ${warning}`))
    }

    if (result.errors.length > 0) {
      log.error('Matter configuration errors:')
      result.errors.forEach(error => log.error(`  - ${error}`))
    }

    return result
  }

  private static validatePort(config: Record<string, unknown>, result: MatterConfigValidationResult): void {
    const port = config.port

    if (port !== undefined && port !== null) {
      if (typeof port === 'number') {
        const validation = validatePort(port, true)
        if (!validation.valid) {
          result.errors.push(validation.error!)
        } else if (validation.warning) {
          result.warnings.push(validation.warning)
        }
      } else {
        result.errors.push(`Port must be a number, got ${typeof port}.`)
      }
    }
  }

  /**
   * Validate child Matter configuration (_bridge.matter property)
   */
  static validateChildMatterConfig(
    config: PlatformConfig | AccessoryConfig,
    configType: 'platform' | 'accessory',
    identifier: string,
  ): MatterConfigValidationResult {
    const result: MatterConfigValidationResult = {
      isValid: true,
      errors: [],
      warnings: [],
    }

    // If no _bridge.matter property, no validation needed
    if (!config._bridge?.matter) {
      return result
    }

    const matterConfig = config._bridge.matter
    const prefix = `Child Matter bridge for ${configType} "${identifier}"`

    // Validate port if specified
    if (matterConfig.port !== undefined) {
      const validation = validatePort(matterConfig.port, false)
      if (!validation.valid) {
        result.errors.push(`${prefix}: ${validation.error}`)
        result.isValid = false
      }
    } else {
      result.warnings.push(`${prefix}: No port specified. Port will be auto-allocated.`)
    }

    // Check for port conflicts with HAP bridge
    if (config._bridge && config._bridge.matter) {
      // Ensure ports don't conflict if both HAP and Matter are configured
      if (config._bridge.port && matterConfig.port) {
        const proximityWarning = checkPortProximity(config._bridge.port, matterConfig.port)
        if (proximityWarning) {
          result.warnings.push(`${prefix}: ${proximityWarning}`)
        }
      }
    }

    // Log validation results
    if (result.errors.length > 0) {
      log.error(`${prefix} validation errors:`)
      result.errors.forEach(error => log.error(`  - ${error}`))
    }

    if (result.warnings.length > 0) {
      log.warn(`${prefix} validation warnings:`)
      result.warnings.forEach(warning => log.warn(`  - ${warning}`))
    }

    return result
  }

  /**
   * Validate all child Matter configurations in a config
   */
  static validateAllChildMatterConfigs(
    platforms: PlatformConfig[],
    accessories: AccessoryConfig[],
  ): MatterConfigValidationResult {
    const result: MatterConfigValidationResult = {
      isValid: true,
      errors: [],
      warnings: [],
    }

    const usedPorts = new Set<number>()

    // Validate platform _bridge.matter configs
    for (const platform of platforms) {
      if (platform._bridge?.matter) {
        const validation = this.validateChildMatterConfig(
          platform,
          'platform',
          platform.platform || 'unknown',
        )

        result.errors.push(...validation.errors)
        result.warnings.push(...validation.warnings)
        result.isValid = result.isValid && validation.isValid

        // Check for port conflicts
        if (platform._bridge.matter.port) {
          if (usedPorts.has(platform._bridge.matter.port)) {
            result.errors.push(`Duplicate Matter port ${platform._bridge.matter.port} detected. Each Matter bridge must use a unique port.`)
            result.isValid = false
          }
          usedPorts.add(platform._bridge.matter.port)
        }
      }
    }

    // Validate accessory _bridge.matter configs
    for (const accessory of accessories) {
      if (accessory._bridge?.matter) {
        const validation = this.validateChildMatterConfig(
          accessory,
          'accessory',
          accessory.accessory || 'unknown',
        )

        result.errors.push(...validation.errors)
        result.warnings.push(...validation.warnings)
        result.isValid = result.isValid && validation.isValid

        // Check for port conflicts
        if (accessory._bridge.matter.port) {
          if (usedPorts.has(accessory._bridge.matter.port)) {
            result.errors.push(`Duplicate Matter port ${accessory._bridge.matter.port} detected. Each Matter bridge must use a unique port.`)
            result.isValid = false
          }
          usedPorts.add(accessory._bridge.matter.port)
        }
      }
    }

    return result
  }
}
